-
Notifications
You must be signed in to change notification settings - Fork 375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: addressability #2731
base: master
Are you sure you want to change the base?
fix: addressability #2731
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2731 +/- ##
==========================================
+ Coverage 60.87% 61.06% +0.19%
==========================================
Files 563 564 +1
Lines 75193 75448 +255
==========================================
+ Hits 45770 46071 +301
+ Misses 26055 25988 -67
- Partials 3368 3389 +21
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
start looking, this seems to be a missing case: package main
import "fmt"
type MyStruct struct {
Mp *int
}
func makeT() MyStruct {
x := 10
return MyStruct{Mp: &x}
}
func main() {
p := &makeT().Mp // This would cause an error because you cannot take the address of a struct field when the struct is a direct return value of a function.
fmt.Println(p)
} |
gnovm/pkg/gnolang/preprocess.go
Outdated
baseType := baseOf(ft.Results[0].Type) | ||
switch baseType.(type) { | ||
case *PointerType, *SliceType: | ||
n.IsAddressable = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this is out of scope, but the error should be about assignment mismatch.
package main
func foo() ([]int, []string) {
return []int{1, 2, 3}, []string{"a", "b", "c"}
}
func main() {
r1 := &foo()
}
// Error:
// cannot take address of foo<VPBlock(3,0)>():
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is actually in scope; you're right that in this case it doesn't make sense for the addressability error message to supersede the results mismatch. In fact, the addressability message doesn't make sense because it is trying to take the address of multiple values. Addressed this here: 3f4f1b6
another one out of scope too: 😆 package main
type MyInt int
func main() {
_ = &MyInt
_ = MyInt
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bunch of proposed reorgs, overall implementation looks good, good job 🎉
gnovm/pkg/gnolang/nodes.go
Outdated
Args Exprs // function arguments, if any. | ||
Varg bool // if true, final arg is variadic. | ||
NumArgs int // len(Args) or len(Args[0].Results) | ||
Addressability Addressability |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the cases like this where the addressability is assigned during preprocess, what do you think about moving Addressability as an attribute?
The reason why I say this is that we currently have a bunch of information which is not actually persisted, but recovered by using Preprocess
. The Expr
types here contain in their struct only information which comes directly out of the AST representation; not from preprocessing. I'm not entirely sure of why it's designed this way; but I think for consistency we should maintain the split between "preprocessed information" in Attributes, and AST information in the struct themselves.
If addressability is an attribute, I also wonder if there's a way to remove the specific type and turn this into Addressable() bool
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there is a good way to make an Addressable() bool
method due to reasons I outlined in responses to other comments -- there are one or more cases where addressability is not applicable so the preprocessor should handle execution as usual. That being said, while many other attributes apply only exist some of the time, the Addressability attribute exists for all addressable expressions -- everywhere it appears. For ease of access, I'd prefer not to make this an attribute.
@@ -1671,6 +1768,30 @@ func (sb *StaticBlock) GetIsConst(store Store, n Name) bool { | |||
} | |||
} | |||
|
|||
func (sb *StaticBlock) getAt(store Store, path ValuePath) *StaticBlock { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func (sb *StaticBlock) getAt(store Store, path ValuePath) *StaticBlock { | |
func (sb *StaticBlock) GetBlockNodeForPath(store Store, path ValuePath) *StaticBlock { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can fix this issue #2840 on this PR, or it is out of scope ?
(We should prohibit assignments to non-addressable attributes.)
Co-authored-by: ltzmaxwell <ltz.maxwell@gmail.com>
@ltzmaxwell to finish the work on this PR. |
Closes #2299.
This PR enforces addressability rules from the go spec. Basically, you can't take references of values that don't have addresses, which makes sense. I think it's important to have the VM's behavior match Go's in this regard. If this isn't in place before we launch and we decide to do it later, we run the risk of breaking realms with code that doesn't adhere to the addressability rules. Omitting addressability rules may also have unforeseen future consequences when we decide to make the VM compatible with newer Go language features.
Contributors' checklist...
BREAKING CHANGE: xxx
message was included in the description